home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cfengine-1.5.3 / src / item-ext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-26  |  38.3 KB  |  1,853 lines

  1. /* cfengine for GNU
  2.  
  3.         Copyright (C) 1995,1999
  4.         Free Software Foundation, Inc.
  5.  
  6.    This file is part of GNU cfengine - written and maintained 
  7.    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
  8.    Dept. of Theoretical physics, University of Oslo
  9.  
  10.    This program is free software; you can redistribute it and/or modify it
  11.    under the terms of the GNU General Public License as published by the
  12.    Free Software Foundation; either version 2, or (at your option) any
  13.    later version.
  14.  
  15.    This program is distributed in the hope that it will be useful,
  16.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.    GNU General Public License for more details.
  19.  
  20.   You should have received a copy of the GNU General Public License
  21.   along with this program; if not, write to the Free Software
  22.   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
  23.  
  24. */
  25.  
  26.  
  27. /*********************************************************************/
  28. /*                                                                   */
  29. /*  TOOLKIT: the "item extension" object library for cfengine        */
  30. /*                                                                   */
  31. /*********************************************************************/
  32.  
  33. #include "cf.defs.h"
  34. #include "cf.extern.h"
  35.  
  36. /*********************************************************************/
  37.  
  38. IsWildItemIn(list,item)
  39.  
  40.    /* Checks whether item matches a list of wildcards */
  41.  
  42. struct Item *list;
  43. char *item;
  44.  
  45. { struct Item *ptr;
  46.  
  47. for (ptr = list; ptr != NULL; ptr=ptr->next)
  48.    {
  49.    if (IsExcluded(ptr->classes))
  50.       {
  51.       continue;
  52.       }
  53.  
  54.    if (WildMatch(ptr->name,item))
  55.       {
  56.       return(true);
  57.       }
  58.    }
  59. return(false);
  60. }
  61.  
  62. /*********************************************************************/
  63.  
  64. InsertItemAfter (filestart,ptr,string)
  65.  
  66. struct Item *ptr, **filestart;
  67. char *string;
  68.  
  69. { struct Item *ip;
  70.   char *sp;
  71.  
  72. EditVerbose("Inserting %s \n",string);
  73.  
  74. if ((ip = (struct Item *)malloc(sizeof(struct Item))) == NULL)
  75.    {
  76.    CfLog(cferror,"","Can't allocate memory in InsertItemAfter()");
  77.    FatalError("");
  78.    }
  79.  
  80. if ((sp = malloc(strlen(string)+1)) == NULL)
  81.    {
  82.    CfLog(cferror,"","Can't allocate memory in InsertItemAfter()");
  83.    FatalError("");
  84.    }
  85.  
  86. if (CURRENTLINEPTR == NULL)   /* File is empty */
  87.    {
  88.    if (filestart == NULL)
  89.       {
  90.       *filestart = ip;
  91.       ip->next = NULL;
  92.       }
  93.    else
  94.       {
  95.       ip->next = (*filestart)->next;
  96.       (*filestart)->next = ip;
  97.       }
  98.    
  99.    strcpy(sp,string);
  100.    ip->name = sp;
  101.    ip->classes = NULL;
  102.    CURRENTLINEPTR = ip;
  103.    CURRENTLINENUMBER = 1;
  104.    }
  105. else
  106.    {
  107.    ip->next = CURRENTLINEPTR->next;
  108.    CURRENTLINENUMBER++;
  109.    CURRENTLINEPTR->next = ip;
  110.    CURRENTLINEPTR = ip;
  111.    strcpy(sp,string);
  112.    ip->name = sp;
  113.    ip->classes = NULL;
  114.    }
  115.  
  116. NUMBEROFEDITS++;
  117.  
  118. return;
  119. }
  120.  
  121.  
  122. /*********************************************************************/
  123.  
  124. InsertFileAfter (filestart,ptr,string)
  125.  
  126. struct Item *ptr, **filestart;
  127. char *string;
  128.  
  129. { struct Item *ip, *old;
  130.   char *sp;
  131.   FILE *fp;
  132.   char linebuf[bufsize];
  133.  
  134. EditVerbose("Edit: Inserting file %s \n",string);
  135.  
  136. if ((fp=fopen(string,"r")) == NULL)
  137.    {
  138.    Verbose("Could not open file %s\n",string);
  139.    return;
  140.    }
  141.  
  142. while(!feof(fp))
  143.    {
  144.    ReadLine(linebuf,bufsize,fp);
  145.    
  146.    if ((ip = (struct Item *)malloc(sizeof(struct Item))) == NULL)
  147.       {
  148.       CfLog(cferror,"","Can't allocate memory in InsertItemAfter()");
  149.       FatalError("");
  150.       }
  151.    
  152.    if ((sp = malloc(strlen(linebuf)+1)) == NULL)
  153.       {
  154.       CfLog(cferror,"","Can't allocate memory in InsertItemAfter()");
  155.       FatalError("");
  156.       }
  157.  
  158.    if (CURRENTLINEPTR == NULL)
  159.       {
  160.       if (*filestart == NULL)
  161.      {
  162.      *filestart = ip;
  163.      ip->next = NULL;
  164.      }
  165.       else
  166.      {
  167.      ip->next = (*filestart)->next;
  168.      (*filestart)->next = ip;        
  169.      }
  170.  
  171.       strcpy(sp,linebuf);
  172.       ip->name = sp;
  173.       ip->classes = NULL;
  174.       CURRENTLINEPTR = ip;
  175.       CURRENTLINENUMBER = 1;
  176.       } 
  177.    else
  178.       {
  179.       ip->next = CURRENTLINEPTR->next;
  180.       CURRENTLINEPTR->next = ip;
  181.       CURRENTLINEPTR=ip;
  182.       CURRENTLINENUMBER++;
  183.       strcpy(sp,linebuf);
  184.       ip->name = sp;
  185.       ip->classes = NULL;
  186.       }
  187.    }
  188.  
  189. NUMBEROFEDITS++;
  190.  
  191. fclose(fp);
  192.  
  193. return;
  194. }
  195.  
  196.  
  197. /*********************************************************************/
  198.  
  199. struct Item *LocateNextItemContaining(list,string) 
  200.  
  201. struct Item *list;
  202. char *string;
  203.  
  204. { struct Item *ip;
  205.  
  206. for (ip = list; ip != NULL; ip=ip->next)
  207.    {
  208.    if (ip->name == NULL)
  209.       {
  210.       continue;
  211.       }
  212.    
  213.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  214.       {
  215.       EditVerbose("Aborting search, regex %s matches line\n",VEDITABORT);
  216.       return NULL;
  217.       }
  218.    
  219.    if (strstr(ip->name,string))
  220.       {
  221.       return ip;
  222.       }
  223.    }
  224.  
  225. return NULL;
  226. }
  227.  
  228. /*********************************************************************/
  229.  
  230. struct Item *LocateNextItemMatching(list,string) 
  231.  
  232. struct Item *list;
  233. char *string;
  234.  
  235. { struct Item *ip;
  236.   regex_t rx,rxcache;
  237.   regmatch_t pmatch;
  238.   size_t nmatch = 1;
  239.   int ret;
  240.  
  241.  
  242. if (regcomp(&rxcache,string, REG_EXTENDED) != 0)
  243.    {
  244.    sprintf(OUTPUT,"Regular expression error for %s\n",string);
  245.    CfLog(cferror,OUTPUT,"regcomp");
  246.    return NULL;
  247.    }
  248.  
  249. for (ip = list; (ip != NULL); ip=ip->next)
  250.    {
  251.    if (ip->name == NULL)
  252.       {
  253.       continue;
  254.       }
  255.    
  256.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  257.       {
  258.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  259.       regfree(&rx);
  260.       return NULL;
  261.       }
  262.  
  263.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */   
  264.    if (regexec(&rx,ip->name,1,&pmatch,0) == 0)
  265.       {
  266.       if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name)))
  267.      {
  268.          regfree(&rx);
  269.      return ip;
  270.      }
  271.       }
  272.    }
  273.  
  274. /* regfree(&rx); */
  275. return NULL;
  276. }
  277.  
  278. /*********************************************************************/
  279.  
  280. struct Item *LocateNextItemStarting(list,string) 
  281.  
  282. struct Item *list;
  283. char *string;
  284.  
  285. { struct Item *ip;
  286.  
  287. for (ip = list; (ip != NULL); ip=ip->next)
  288.    {
  289.    if (ip->name == NULL)
  290.       {
  291.       continue;
  292.       }
  293.  
  294.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  295.       {
  296.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  297.       return NULL;
  298.       }
  299.       
  300.    if (strncmp(ip->name,string,strlen(string)) == 0)
  301.       {
  302.       return ip;
  303.       }
  304.    }
  305.  
  306. return NULL;
  307. }
  308.  
  309. /*********************************************************************/
  310.  
  311. struct Item *LocateItemMatchingRegExp(list,string) 
  312.  
  313. struct Item *list;
  314. char *string;
  315.  
  316. { struct Item *ip;
  317.   regex_t rx,rxcache;
  318.   regmatch_t pmatch;
  319.   size_t nmatch = 1;
  320.   int line = CURRENTLINENUMBER;
  321.  
  322. Debug("LocateItemMatchingRexExp(%s,%s)\n",list->name,string);
  323.   
  324. if (regcomp(&rxcache,string, REG_EXTENDED) != 0)
  325.    {
  326.    sprintf(OUTPUT,"Regular expression error for %s\n",string);
  327.    CfLog(cferror,OUTPUT,"regcomp");
  328.    return NULL;
  329.    }
  330.  
  331. for (ip = list; (ip != NULL); ip=ip->next, line++)
  332.    {
  333.    if (ip->name == NULL)
  334.       {
  335.       continue;
  336.       }
  337.  
  338.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  339.       {
  340.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  341.       regfree(&rx);
  342.       return NULL;
  343.       }
  344.    
  345.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */      
  346.    if (regexec(&rx,ip->name,1,&pmatch,0) == 0)
  347.       {
  348.       if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name)))
  349.      {
  350.      EditVerbose("Edit: Search ended at line %d\n",line);
  351.      EditVerbose("Edit: (Found %s)\n",ip->name);
  352.      CURRENTLINENUMBER = line;
  353.      CURRENTLINEPTR = ip;
  354.          regfree(&rx);
  355.      return ip;
  356.      }
  357.       }
  358.    }
  359.  
  360. EditVerbose("Edit: Search for %s failed. Current line still %d\n",string,CURRENTLINENUMBER);
  361. /* regfree(&rx); */
  362. return NULL;
  363. }
  364.  
  365. /*********************************************************************/
  366.  
  367. struct Item *LocateItemContainingRegExp(list,string) 
  368.  
  369. struct Item *list;
  370. char *string;
  371.  
  372. { struct Item *ip;
  373.   regex_t rx,rxcache;
  374.   regmatch_t pmatch;
  375.   size_t nmatch = 1;
  376.   int line = 1;
  377.  
  378. if (regcomp(&rxcache,string, REG_EXTENDED) != 0)
  379.    {
  380.    sprintf(OUTPUT,"Regular expression error for %s\n",string);
  381.    CfLog(cferror,OUTPUT,"regcomp");
  382.    return NULL;
  383.    }
  384.  
  385. for (ip = list; (ip != NULL); ip=ip->next)
  386.    {
  387.    if (ip->name == NULL)
  388.       {
  389.       continue;
  390.       }
  391.  
  392.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  393.       {
  394.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  395.       regfree(&rx);
  396.       return NULL;
  397.       }
  398.  
  399.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */   
  400.    if (regexec(&rx,ip->name,1,&pmatch,0) == 0)
  401.       {
  402.       EditVerbose("Search ended at line %d\n",line);
  403.       CURRENTLINENUMBER = line;
  404.       CURRENTLINEPTR = ip;
  405.       regfree(&rx);
  406.       return ip;
  407.       }
  408.    }
  409.  
  410. EditVerbose("Search for %s failed. Current line still %d\n",string,CURRENTLINENUMBER);
  411.  
  412. /* regfree(&rx);*/
  413. return NULL;
  414. }
  415.  
  416. /********************************************************************/
  417.  
  418. DeleteToRegExp(filestart,string)
  419.  
  420.   /* Delete up to and including a line matching the regex */
  421.  
  422. struct Item **filestart;
  423. char *string;
  424.  
  425. { struct Item *ip, *ip_prev, *ip_end = NULL;
  426.   int linefound = false, done;
  427.   regex_t rx,rxcache;
  428.   regmatch_t pmatch;
  429.   size_t nmatch = 1;
  430.  
  431. Debug2("DeleteToRegExp(list,%s)\n",string);
  432.  
  433. if (CURRENTLINEPTR == NULL)  /* Shouldn't happen */
  434.    {
  435.    CfLog(cferror,"File line-pointer undefined during editfile action\n","");
  436.    return true;
  437.    }
  438.  
  439. if (regcomp(&rxcache,string, REG_EXTENDED) != 0)
  440.    {
  441.    sprintf(OUTPUT,"Regular expression error for %s\n",string);
  442.    CfLog(cferror,OUTPUT,"regcomp");
  443.    return false;
  444.    }
  445.  
  446. for (ip = CURRENTLINEPTR; (ip != NULL); ip=ip->next)
  447.    {
  448.    if (ip->name == NULL)
  449.       {
  450.       continue;
  451.       }
  452.  
  453.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  454.       {
  455.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  456.       regfree(&rx);
  457.       return false;
  458.       }
  459.  
  460.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */   
  461.    if (regexec(&rx,ip->name,1,&pmatch,0) == 0)
  462.       {
  463.       if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name)))
  464.      {
  465.      linefound = true;
  466.      ip_end = ip;
  467.      break;
  468.      }
  469.       }
  470.    }
  471.  
  472. if (! linefound)
  473.    {
  474.    return false;
  475.    }
  476.  
  477. done = false;
  478.  
  479. for (ip_prev = *filestart; ip_prev != CURRENTLINEPTR && ip_prev->next != CURRENTLINEPTR; ip_prev=ip_prev->next)
  480.    {
  481.    }
  482.  
  483. for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR)
  484.    {
  485.    if (ip->name == NULL)
  486.       {
  487.       continue;
  488.       }
  489.  
  490.  
  491.    if (ip == ip_end)
  492.       {
  493.       EditVerbose("Edit: terminating line: %s (Done)\n",ip->name);
  494.       done = true;
  495.       }
  496.  
  497.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  498.       {
  499.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  500.       regfree(&rx);
  501.       return false;
  502.       }
  503.  
  504.    EditVerbose("Edit: delete line %s\n",ip->name);
  505.    NUMBEROFEDITS++;
  506.    CURRENTLINEPTR = ip->next;
  507.  
  508.    if (ip == *filestart)
  509.       {
  510.       *filestart = ip->next;
  511.       }
  512.    else
  513.       {
  514.       ip_prev->next = ip->next;
  515.       }
  516.  
  517.    free (ip->name);
  518.    free ((char *)ip);
  519.  
  520.    if (done)
  521.       {
  522.       break;
  523.       }
  524.    }
  525.  
  526. /* regfree(&rx); */
  527. return true;
  528. }
  529.  
  530. /*********************************************************************/
  531.  
  532. DeleteItemStarting(list,string) /* deletes first item to match the string */
  533.  
  534. struct Item **list;
  535. char *string;
  536.  
  537. { struct Item *ip, *next, *last = NULL;
  538.  
  539. if (list == NULL)
  540.    {
  541.    return false;
  542.    }
  543.  
  544. for (ip = *list; ip != NULL; ip=ip->next)
  545.    {
  546.    if (ip->name == NULL)
  547.       {
  548.       continue;
  549.       }
  550.  
  551.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  552.       {
  553.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  554.       return false;
  555.       }
  556.       
  557.    if (strncmp(ip->name,string,strlen(string)) == 0)
  558.       {
  559.       if (ip == *list)
  560.          {
  561.          free((*list)->name);
  562.          if (ip->classes != NULL) 
  563.         {
  564.             free(ip->classes);
  565.         }
  566.          *list = ip->next;
  567.          free((char *)ip);
  568.  
  569.          EditVerbose("Deleted item %s\n",ip->name);
  570.          NUMBEROFEDITS++;
  571.          return true;
  572.          }
  573.       else
  574.          {
  575.          last->next = ip->next; 
  576.          free(ip->name);
  577.          if (ip->classes != NULL) 
  578.         {
  579.             free(ip->classes);
  580.         }
  581.          free((char *)ip);
  582.  
  583.          EditVerbose("Deleted item %s\n",string);
  584.          NUMBEROFEDITS++;
  585.          return true;
  586.          }
  587.  
  588.       }
  589.    last = ip;
  590.    }
  591.  
  592. return false;
  593. }
  594.  
  595. /*********************************************************************/
  596.  
  597. DeleteItemMatching(list,string) /* deletes first item to match the regex */
  598.  
  599. struct Item **list;
  600. char *string;
  601.  
  602. { struct Item *ip, *next, *last;
  603.   regex_t rx,rxcache;
  604.   regmatch_t pmatch;
  605.   size_t nmatch = 1;
  606.  
  607.  if (regcomp(&rxcache,string, REG_EXTENDED) != 0)
  608.    {
  609.    sprintf(OUTPUT,"Regular expression error for %s\n",string);
  610.    CfLog(cferror,OUTPUT,"regcomp");
  611.    return false;
  612.    }
  613.  
  614. for (ip = *list; ip != NULL; ip=ip->next)
  615.    {
  616.    if (ip->name == NULL)
  617.       {
  618.       continue;
  619.       }
  620.  
  621.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  622.       {
  623.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  624.       regfree(&rx);
  625.       return false;
  626.       }
  627.  
  628.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */
  629.    if (regexec(&rx,ip->name,1,&pmatch,0) == 0)
  630.       {
  631.       if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name)))
  632.      {
  633.      if (ip == *list)
  634.         {
  635.         free((*list)->name);
  636.         if (ip->classes != NULL) 
  637.            {
  638.            free(ip->classes);
  639.            }
  640.         *list = ip->next;
  641.         free((char *)ip);
  642.         
  643.         EditVerbose("Deleted item %s\n",string);
  644.         NUMBEROFEDITS++;
  645.             regfree(&rx);
  646.         return true;
  647.         }
  648.      else
  649.         {
  650.         last->next = ip->next; 
  651.         free(ip->name);
  652.         if (ip->classes != NULL) 
  653.            {
  654.            free(ip->classes);
  655.            }
  656.         free((char *)ip);
  657.         
  658.         EditVerbose("Deleted item %s\n",string);
  659.         NUMBEROFEDITS++;
  660.         regfree(&rx);
  661.         return true;
  662.         }
  663.      }
  664.       }
  665.    last = ip;
  666.    }
  667.  
  668. /* regfree(&rx); */
  669. return false;
  670. }
  671.  
  672. /*********************************************************************/
  673.  
  674. DeleteItemContaining(list,string) /* deletes first item to match the string */
  675.  
  676. struct Item **list;
  677. char *string;
  678.  
  679. { struct Item *ip, *next, *last;
  680. return false;
  681. Debug("DeleteItemContaining(%s)\n",string);
  682.  
  683. for (ip = *list; ip != NULL; ip=ip->next)
  684.    {
  685.    if (ip->name == NULL)
  686.       {
  687.       continue;
  688.       }
  689.  
  690.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  691.       {
  692.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  693.       return false;
  694.       }
  695.  
  696.    if (ip->name == NULL)
  697.       {
  698.       continue;
  699.       }
  700.       
  701.    if (strstr(ip->name,string))
  702.       {
  703.       if (ip == *list)
  704.          {
  705.          free((*list)->name);
  706.          *list = ip->next;
  707.          if (ip->classes != NULL) 
  708.         {
  709.             free(ip->classes);
  710.         }
  711.          free((char *)ip);
  712.  
  713.          EditVerbose("Deleted item %s\n",ip->name);
  714.          NUMBEROFEDITS++;
  715.          return true;
  716.          }
  717.       else
  718.          {
  719.          last->next = ip->next; 
  720.          free(ip->name);
  721.          if (ip->classes != NULL) 
  722.         {
  723.             free(ip->classes);
  724.         }
  725.          free((char *)ip);
  726.  
  727.          EditVerbose("Deleted item %s\n",ip->name);
  728.          NUMBEROFEDITS++;
  729.          return true;
  730.          }
  731.  
  732.       }
  733.    last = ip;
  734.    }
  735.  
  736. return false;
  737. }
  738.  
  739.  
  740. /*********************************************************************/
  741.  
  742. CommentItemStarting(list,string,comm,end)
  743.  
  744. struct Item **list;
  745. char *string,*comm,*end;
  746.  
  747. { struct Item *ip;
  748.   char buff[bufsize];
  749.  
  750. for (ip = *list; ip != NULL; ip=ip->next)
  751.    {
  752.    if (ip->name == NULL)
  753.       {
  754.       continue;
  755.       }
  756.  
  757.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  758.       {
  759.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  760.       return false;
  761.       }
  762.       
  763.    if (strncmp(ip->name,string,strlen(string)) == 0)
  764.       {
  765.       if (strlen(ip->name)+strlen(comm)+strlen(end)+2 > bufsize)
  766.          {
  767.          CfLog(cferror,"Bufsize overflow while commenting line - abort\n","");
  768.          return false;
  769.          }
  770.  
  771.       if (strncmp(ip->name,comm,strlen(comm))== 0)
  772.          {
  773.          continue;
  774.          }
  775.  
  776.       EditVerbose("Commenting %s%s%s\n",comm,ip->name,end);
  777.  
  778.       sprintf(buff,"%s%s%s",comm,ip->name,end);
  779.       free(ip->name);
  780.  
  781.       if ((ip->name = malloc(strlen(buff)+1)) == NULL)
  782.          {
  783.          CfLog("malloc in CommentItemStarting\n","");
  784.          FatalError("");;
  785.          }
  786.  
  787.       strcpy(ip->name,buff);
  788.       NUMBEROFEDITS++;
  789.  
  790.       return true;
  791.       }
  792.    }
  793.  
  794. return false;
  795. }
  796.  
  797. /*********************************************************************/
  798.  
  799. CommentItemContaining(list,string,comm,end)
  800.  
  801. struct Item **list;
  802. char *string,*comm,*end;
  803.  
  804. { struct Item *ip;
  805.   char buff[bufsize];
  806.  
  807. for (ip = *list; ip != NULL; ip=ip->next)
  808.    {
  809.    if (ip->name == NULL)
  810.       {
  811.       continue;
  812.       }
  813.  
  814.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  815.       {
  816.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  817.       return false;
  818.       }
  819.       
  820.    if (strstr(ip->name,string))
  821.       {
  822.       if (strlen(ip->name)+strlen(comm)+strlen(end)+2 > bufsize)
  823.          {
  824.          CfLog("Bufsize overflow while commenting line - abort\n","");
  825.          return false;
  826.          }
  827.  
  828.       if (strncmp(ip->name,comm,strlen(comm))== 0)
  829.          {
  830.          continue;
  831.          }
  832.  
  833.       EditVerbose("Commenting %s%s%s\n",comm,ip->name,end);
  834.  
  835.       sprintf(buff,"%s%s%s",comm,ip->name,end);
  836.       free(ip->name);
  837.  
  838.       if ((ip->name = malloc(strlen(buff)+1)) == NULL)
  839.          {
  840.          CfLog(cferror,"malloc in CommentItemContaining\n","");
  841.          FatalError("");;
  842.          }
  843.  
  844.       strcpy(ip->name,buff);
  845.       NUMBEROFEDITS++;
  846.  
  847.       return true;
  848.       }
  849.    }
  850.  
  851. return false;
  852. }
  853.  
  854. /*********************************************************************/
  855.  
  856. CommentItemMatching(list,string,comm,end)
  857.  
  858. struct Item **list;
  859. char *string,*comm,*end;
  860.  
  861. { struct Item *ip;
  862.   char buff[bufsize];
  863.   regex_t rx,rxcache;
  864.   regmatch_t pmatch;
  865.   size_t nmatch = 1;
  866.  
  867. if (regcomp(&rxcache,string, REG_EXTENDED) != 0)
  868.    {
  869.    sprintf(OUTPUT,"Regular expression error for %s\n",string);
  870.    CfLog(cferror,OUTPUT,"regcomp");
  871.    return false;
  872.    }
  873.  
  874. for (ip = *list; ip != NULL; ip=ip->next)
  875.    {
  876.    if (ip->name == NULL)
  877.       {
  878.       continue;
  879.       }
  880.  
  881.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  882.       {
  883.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  884.       regfree(&rx);
  885.       return false;
  886.       }
  887.  
  888.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */
  889.    
  890.    if (regexec(&rx,ip->name,1,&pmatch,0) == 0)
  891.       {
  892.       if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name)))
  893.      {
  894.      if (strlen(ip->name)+strlen(comm)+strlen(end)+2 > bufsize)
  895.         {
  896.         CfLog(cferror,"Bufsize overflow while commenting line - abort\n","");
  897.             regfree(&rx);
  898.         return false;
  899.         }
  900.      
  901.      if (strncmp(ip->name,comm,strlen(comm)) == 0) /* Already commented */
  902.         {
  903.         continue;
  904.         }
  905.      
  906.      EditVerbose("Commenting %s%s%s\n",comm,ip->name,end);
  907.      
  908.      sprintf(buff,"%s%s%s",comm,ip->name,end);
  909.      free(ip->name);
  910.      
  911.      if ((ip->name = malloc(strlen(buff)+1)) == NULL)
  912.         {
  913.         CfLog(cferror,"malloc in CommentItemContaining\n ","");
  914.         FatalError("");;
  915.         }
  916.      
  917.      strcpy(ip->name,buff);
  918.      NUMBEROFEDITS++;
  919.      
  920.          regfree(&rx);
  921.      return true;
  922.      }
  923.       }
  924.    }
  925.  
  926. /* regfree(&rx); */
  927. return false;
  928. }
  929.  
  930. /********************************************************************/
  931.  
  932. UnCommentItemMatching(list,string,comm,end)
  933.  
  934. struct Item **list;
  935. char *string,*comm,*end;
  936.  
  937. { struct Item *ip;
  938.   char *sp, *sp1, *sp2, *spc;
  939.   regex_t rx,rxcache;
  940.   regmatch_t pmatch;
  941.   size_t nmatch = 1;
  942.  
  943. if (regcomp(&rxcache,string, REG_EXTENDED) != 0)
  944.    {
  945.    sprintf(OUTPUT,"Regular expression error for %s\n",string);
  946.    CfLog(cferror,OUTPUT,"regcomp");
  947.    return false;
  948.    }
  949.  
  950. for (ip = *list; ip != NULL; ip=ip->next)
  951.    {
  952.    if (ip->name == NULL)
  953.       {
  954.       continue;
  955.       }
  956.  
  957.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */
  958.    
  959.    if (regexec(&rx,ip->name,1,&pmatch,0) == 0)
  960.       {
  961.       if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name)))
  962.      {
  963.      if (strlen(ip->name)+strlen(comm)+strlen(end)+2 > bufsize)
  964.         {
  965.         CfLog(cferror,"Bufsize overflow while commenting line - abort\n","");
  966.             regfree(&rx);
  967.         return false;
  968.         }
  969.      
  970.      if (strstr(ip->name,comm) == NULL)
  971.         {
  972.         CURRENTLINEPTR = ip->next;
  973.         continue;
  974.         }
  975.      
  976.      EditVerbose("Uncomment line %s\n",ip->name);
  977.      CURRENTLINEPTR = ip->next;
  978.      
  979.      if ((sp = malloc(strlen(ip->name)+2)) == NULL)
  980.         {
  981.         CfLog(cferror,"No Memory in UnCommentNLines\n","malloc");
  982.             regfree(&rx);
  983.         return false;
  984.         }
  985.      
  986.      spc = sp;
  987.      
  988.      for (sp1 = ip->name; isspace(*sp1); sp1++)
  989.         {
  990.         *spc++ = *sp1;
  991.         }
  992.      
  993.      *spc = '\0';
  994.      
  995.      sp2 = ip->name+strlen(ip->name);
  996.      
  997.      if ((strlen(end) != 0) && (strstr(ip->name,end) != NULL))
  998.         {
  999.         for (sp2 = ip->name+strlen(ip->name); strncmp(sp2,end,strlen(end)) != 0; sp2--)
  1000.            {
  1001.            }
  1002.         
  1003.         *sp2 = '\0';
  1004.         }
  1005.      
  1006.      strcat(sp,sp1+strlen(comm));
  1007.      
  1008.      if (sp2 != ip->name+strlen(ip->name))
  1009.         {
  1010.         strcat(sp,sp2+strlen(end));
  1011.         }
  1012.      
  1013.      if (strcmp(sp,ip->name) != 0)
  1014.         {
  1015.         NUMBEROFEDITS++;
  1016.         }
  1017.      
  1018.      free(ip->name);
  1019.      ip->name = sp;
  1020.          regfree(&rx);
  1021.      return true;
  1022.      }
  1023.       }
  1024.    }
  1025.  
  1026. /* regfree(&rx); */
  1027. return false;
  1028. }
  1029.  
  1030. /********************************************************************/
  1031.  
  1032. UnCommentItemContaining(list,string,comm,end)
  1033.  
  1034. struct Item **list;
  1035. char *string,*comm,*end;
  1036.  
  1037. { struct Item *ip;
  1038.   char buff[bufsize];
  1039.   char *sp, *sp1, *sp2, *spc;
  1040.  
  1041. for (ip = *list; ip != NULL; ip=ip->next)
  1042.    {
  1043.    if (ip->name == NULL)
  1044.       {
  1045.       continue;
  1046.       }
  1047.  
  1048.    if (strstr(ip->name,string))
  1049.       {
  1050.       if (strstr(ip->name,comm) == NULL)
  1051.          {
  1052.          CURRENTLINEPTR = ip->next;
  1053.          continue;
  1054.          }
  1055.  
  1056.       EditVerbose("Uncomment line %s\n",ip->name);
  1057.       CURRENTLINEPTR = ip->next;
  1058.  
  1059.       if ((sp = malloc(strlen(ip->name)+2)) == NULL)
  1060.          {
  1061.          CfLog(cferror,"No memory in UnCommentNLines\n","malloc");
  1062.          return false;
  1063.          }
  1064.  
  1065.       spc = sp;
  1066.    
  1067.       for (sp1 = ip->name; isspace(*sp1); sp1++)
  1068.          {
  1069.          *spc++ = *sp1;
  1070.          }
  1071.  
  1072.       *spc = '\0';
  1073.  
  1074.       sp2 = ip->name+strlen(ip->name);
  1075.  
  1076.       if ((strlen(end) != 0) && (strstr(ip->name,end) != NULL))
  1077.          {
  1078.          for (sp2 = ip->name+strlen(ip->name); strncmp(sp2,end,strlen(end)) != 0; sp2--)
  1079.             {
  1080.             }
  1081.  
  1082.          *sp2 = '\0';
  1083.          }
  1084.  
  1085.       strcat(sp,sp1+strlen(comm));
  1086.  
  1087.       if (sp2 != ip->name+strlen(ip->name))
  1088.          {
  1089.          strcat(sp,sp2+strlen(end));
  1090.          }
  1091.  
  1092.       if (strcmp(sp,ip->name) != 0)
  1093.          {
  1094.          NUMBEROFEDITS++;
  1095.          }
  1096.    
  1097.       free(ip->name);
  1098.       ip->name = sp;
  1099.       return true;
  1100.       }
  1101.    }
  1102.  
  1103. return false;
  1104. }
  1105.  
  1106.  
  1107. /********************************************************************/
  1108.  
  1109. CommentToRegExp(filestart,string,comm,end)
  1110.  
  1111.   /* Delete up to and including a line matching the regex */
  1112.  
  1113. struct Item **filestart;
  1114. char *string, *comm, *end;
  1115.  
  1116. { struct Item *ip, *ip_end = NULL;
  1117.   int linefound = false, done;
  1118.   char *sp;
  1119.   regex_t rx,rxcache;
  1120.   regmatch_t pmatch;
  1121.   size_t nmatch = 1;
  1122.   
  1123.  
  1124.  
  1125. Debug2("CommentToRegExp(list,%s %s)\n",comm,string);
  1126.  
  1127. if (CURRENTLINEPTR == NULL)  /* Shouldn't happen */
  1128.    {
  1129.    CfLog(cferror,"File line-pointer undefined during editfile action\n","");
  1130.    return true;
  1131.    }
  1132.  
  1133. if (regcomp(&rxcache,string, REG_EXTENDED) != 0)
  1134.    {
  1135.    sprintf(OUTPUT,"Regular expression error for %s\n",string);
  1136.    CfLog(cferror,OUTPUT,"regcomp");
  1137.    return false;
  1138.    }
  1139.  
  1140. for (ip = CURRENTLINEPTR; (ip != NULL); ip=ip->next)
  1141.    {
  1142.    if (ip->name == NULL)
  1143.       {
  1144.       continue;
  1145.       }
  1146.  
  1147.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  1148.       {
  1149.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  1150.       regfree(&rx);
  1151.       return false;
  1152.       }
  1153.  
  1154.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */   
  1155.    if (regexec(&rx,ip->name,1,&pmatch,0) == 0)
  1156.       {
  1157.       if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name)))
  1158.      {
  1159.      linefound = true;
  1160.      ip_end = ip;
  1161.      break;
  1162.      }
  1163.       }
  1164.    }
  1165.  
  1166. if (! linefound)
  1167.    {
  1168.    return false;
  1169.    }
  1170.  
  1171. done = false;
  1172.  
  1173. for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR)
  1174.    {
  1175.    if (ip == ip_end)
  1176.       {
  1177.       EditVerbose("Terminating line: %s (Done)\n",ip->name);
  1178.       done = true;
  1179.       }
  1180.  
  1181.    EditVerbose("Comment line %s%s%s\n",comm,ip->name, end);
  1182.    NUMBEROFEDITS++;
  1183.    CURRENTLINEPTR = ip->next;
  1184.  
  1185.    if ((sp = malloc(strlen(ip->name)+strlen(comm)+strlen(end)+2)) == NULL)
  1186.       {
  1187.       CfLog(cferror,"No memory in CommentToRegExp\n","malloc");
  1188.       regfree(&rx);
  1189.       return false;
  1190.       }
  1191.  
  1192.    strcpy (sp,comm);
  1193.    strcat (sp,ip->name);
  1194.    strcat (sp,end);
  1195.  
  1196.    free (ip->name);
  1197.    ip->name = sp;
  1198.  
  1199.    if (done)
  1200.       {
  1201.       break;
  1202.       }
  1203.    }
  1204.  
  1205. /* regfree(&rx); */
  1206. return true;
  1207. }
  1208.  
  1209. /********************************************************************/
  1210.  
  1211. DeleteSeveralLines (filestart,string)
  1212.  
  1213.   /* Deletes up to N lines from current position */
  1214.  
  1215. struct Item **filestart;
  1216. char *string;
  1217.  
  1218. { struct Item *ip, *ip_prev;
  1219.   int ctr, N = -99, done = false;
  1220.  
  1221. Debug2("DeleteNLines(list,%s)\n",string);
  1222.  
  1223. sscanf(string,"%d", &N);
  1224.  
  1225. if (N < 1)
  1226.    {
  1227.    sprintf(OUTPUT,"Illegal number value in DeleteNLines: %s\n",string);
  1228.    CfLog(cferror,OUTPUT,"");
  1229.    return false;
  1230.    }
  1231.  
  1232.  
  1233. if (CURRENTLINEPTR == NULL)  /* Shouldn't happen */
  1234.    {
  1235.    CfLog(cferror,"File line-pointer undefined during editfile action\n","");
  1236.    return true;
  1237.    }
  1238.  
  1239. for (ip_prev = *filestart; ip_prev->next != CURRENTLINEPTR; ip_prev=ip_prev->next)
  1240.    {
  1241.    }
  1242.  
  1243. ctr = 1;
  1244.  
  1245. for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR)
  1246.    {
  1247.    if (ip->name == NULL)
  1248.       {
  1249.       continue;
  1250.       }
  1251.  
  1252.    if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT))
  1253.       {
  1254.       Verbose("Aborting search, regex %s matches line\n",VEDITABORT);
  1255.       return false;
  1256.       }
  1257.       
  1258.    if (ctr == N)
  1259.       {
  1260.       EditVerbose("Terminating line: %s (Done)\n",ip->name);
  1261.       done = true;
  1262.       }
  1263.  
  1264.    EditVerbose("Delete line %s\n",ip->name);
  1265.    NUMBEROFEDITS++;
  1266.    CURRENTLINEPTR = ip->next;
  1267.  
  1268.    if (ip == *filestart)
  1269.       {
  1270.       *filestart = ip->next;
  1271.       }
  1272.    else
  1273.       {
  1274.       ip_prev->next = ip->next;
  1275.       }
  1276.  
  1277.    free (ip->name);
  1278.    free ((char *)ip);
  1279.    ctr++;
  1280.  
  1281.    if (done)
  1282.       {
  1283.       break;
  1284.       }
  1285.    }
  1286.  
  1287. if (ctr-1 < N)
  1288.    {
  1289.    sprintf(OUTPUT,"DeleteNLines deleted only %d lines (not %d)\n",ctr-1,N);
  1290.    CfLog(cfsilent,OUTPUT,"");
  1291.    }
  1292.  
  1293. return true;
  1294. }
  1295.  
  1296. /********************************************************************/
  1297.  
  1298. struct Item *GotoLastItem (list)
  1299.  
  1300. struct Item *list;
  1301.  
  1302. { struct Item *ip;
  1303.  
  1304. CURRENTLINENUMBER=1;
  1305. CURRENTLINEPTR=list;
  1306.  
  1307. for (ip = list; ip != NULL && ip->next != NULL; ip=ip->next)
  1308.    {
  1309.    CURRENTLINENUMBER++;
  1310.    }
  1311.  
  1312. CURRENTLINEPTR = ip;
  1313.  
  1314. return ip;
  1315. }
  1316.  
  1317. /********************************************************************/
  1318.  
  1319. LineMatches (line,regexp)
  1320.  
  1321. char *line, *regexp;
  1322.  
  1323. { char *err;
  1324.  regex_t rx,rxcache;
  1325.  regmatch_t pmatch;
  1326.  size_t nmatch = 0;
  1327.  
  1328. if (regcomp(&rxcache,regexp, REG_EXTENDED) != 0)
  1329.    {
  1330.    sprintf(OUTPUT,"Error in regular expression %s",regexp);
  1331.    CfLog(cferror,OUTPUT,"regcomp");
  1332.    return false;
  1333.    }
  1334.  
  1335. bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ 
  1336. if (regexec(&rx,line,1,&pmatch,0) == 0)
  1337.    {
  1338.    /* Exact match of whole line */
  1339.    
  1340.    if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(line)))
  1341.       {
  1342.       regfree(&rx);
  1343.       return true;
  1344.       }
  1345.    }
  1346.  
  1347. regfree(&rx);
  1348. return false;
  1349. }
  1350.  
  1351. /********************************************************************/
  1352.  
  1353. GlobalReplace(liststart,search,replace)
  1354.  
  1355. struct Item **liststart;
  1356. char *search, *replace;
  1357.  
  1358. { int i,did;
  1359.   char *sp, *start = NULL;
  1360.   struct Item *ip;
  1361.   struct Item *oldCurrentLinePtr;
  1362.   regex_t rx,rxcache;
  1363.   regmatch_t match;
  1364.   size_t nmatch = 1;
  1365.  
  1366.  EditVerbose("Checking for replace/%s/%s\n",search,replace);
  1367.  
  1368. if (regcomp(&rxcache,search,REG_EXTENDED) != 0)
  1369.    {
  1370.    sprintf(OUTPUT,"Error in regular expression %s",search);
  1371.    CfLog(cferror,OUTPUT,"regcomp");
  1372.    return false;
  1373.    }
  1374.  
  1375. for (ip = *liststart; ip != NULL; ip=ip->next)
  1376.    {
  1377.    if (ip->name == NULL)
  1378.       {
  1379.       continue;
  1380.       }
  1381.  
  1382.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */
  1383.  
  1384.    if (regexec(&rx,ip->name,1,&match,0) == 0)
  1385.       {
  1386.       start = ip->name + match.rm_so;
  1387.       }
  1388.    else
  1389.       {
  1390.       continue;
  1391.       }
  1392.  
  1393.    bzero(VBUFF,bufsize);
  1394.    
  1395.    i = 0;
  1396.  
  1397.    for (sp = ip->name; *sp != '\0'; sp++)
  1398.       {
  1399.       if (sp != start)
  1400.          {
  1401.          VBUFF[i] = *sp;
  1402.          }
  1403.       else
  1404.          {
  1405.          sp += match.rm_eo - match.rm_so - 1;
  1406.          VBUFF[i] = '\0';
  1407.          strcat(VBUFF,replace);
  1408.          i += strlen(replace)-1;
  1409.  
  1410.      bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */
  1411.          if (regexec(&rx,sp,1,&match,0) == 0)
  1412.             {
  1413.             start = sp + match.rm_so;
  1414.             }
  1415.          else
  1416.             {
  1417.             start = 0;
  1418.             }
  1419.          }
  1420.  
  1421.       i++;
  1422.       }
  1423.  
  1424.    Debug("Replace:\n  (%s)\nwith      (%s)\n",ip->name,VBUFF);
  1425.  
  1426.    CURRENTLINEPTR = ip;
  1427.    InsertItemAfter(liststart,ip,VBUFF);
  1428.    oldCurrentLinePtr = CURRENTLINEPTR;                   /* set by Insert */
  1429.    DeleteItem(liststart,ip);
  1430.    ip = oldCurrentLinePtr;
  1431.    }
  1432.  
  1433. regfree(&rx);
  1434. return true;
  1435. }
  1436.  
  1437.  
  1438. /********************************************************************/
  1439.  
  1440. CommentSeveralLines (filestart,string,comm,end)
  1441.  
  1442.   /* Comments up to N lines from current position */
  1443.  
  1444. struct Item **filestart;
  1445. char *string, *comm, *end;
  1446.  
  1447. { struct Item *ip;
  1448.   int ctr, N = -99, done = false;
  1449.   char *sp;
  1450.  
  1451. Debug2("CommentNLines(list,%s)\n",string);
  1452.  
  1453. sscanf(string,"%d", &N);
  1454.  
  1455. if (N < 1)
  1456.    {
  1457.    sprintf(OUTPUT,"Illegal number value in CommentNLines: %s\n",string);
  1458.    CfLog(cferror,OUTPUT,"");
  1459.    return false;
  1460.    }
  1461.  
  1462.  
  1463. if (CURRENTLINEPTR == NULL)  /* Shouldn't happen */
  1464.    {
  1465.    sprintf(OUTPUT,"File line-pointer undefined during editfile action\n");
  1466.    CfLog(cferror,OUTPUT,"");
  1467.    return true;
  1468.    }
  1469.  
  1470. ctr = 1;
  1471.  
  1472. for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR)
  1473.    {
  1474.    if (ip->name == NULL)
  1475.       {
  1476.       continue;
  1477.       }
  1478.  
  1479.    if (ctr > N)
  1480.       {
  1481.       break;
  1482.       }
  1483.    
  1484.    if (ctr == N)
  1485.       {
  1486.       EditVerbose("Terminating line: %s (Done)\n",ip->name);
  1487.       done = true;
  1488.       }
  1489.  
  1490.    for (sp = ip->name; isspace(*sp); sp++)
  1491.       {
  1492.       }
  1493.    
  1494.    if (strncmp(sp,comm,strlen(comm)) == 0)
  1495.       {
  1496.       CURRENTLINEPTR = ip->next;
  1497.       ctr++;
  1498.       continue;
  1499.       }
  1500.  
  1501.    EditVerbose("Comment line %s\n",ip->name);
  1502.    NUMBEROFEDITS++;
  1503.    CURRENTLINEPTR = ip->next;
  1504.  
  1505.    if ((sp = malloc(strlen(ip->name)+strlen(comm)+strlen(end)+2)) == NULL)
  1506.       {
  1507.       CfLog(cferror,"No memory in CommentNLines\n","malloc");
  1508.       return false;
  1509.       }
  1510.  
  1511.    strcpy (sp,comm);
  1512.    strcat (sp,ip->name);
  1513.    strcat (sp,end);
  1514.  
  1515.    free (ip->name);
  1516.    ip->name = sp;
  1517.    ctr++;
  1518.  
  1519.    if (done)
  1520.       {
  1521.       break;
  1522.       }
  1523.    }
  1524.  
  1525. if (ctr-1 < N)
  1526.    {
  1527.    sprintf(OUTPUT,"CommentNLines commented only %d lines (not %d)\n",ctr-1,N);
  1528.    CfLog(cfinform,OUTPUT,"");
  1529.    }
  1530.  
  1531. return true;
  1532. }
  1533.  
  1534. /********************************************************************/
  1535.  
  1536. UnCommentSeveralLines (filestart,string,comm,end)
  1537.  
  1538.   /* Comments up to N lines from current position */
  1539.  
  1540. struct Item **filestart;
  1541. char *string, *comm, *end;
  1542.  
  1543. { struct Item *ip;
  1544.   int ctr, N = -99, done = false;
  1545.   char *sp, *sp1, *sp2, *spc;
  1546.  
  1547. Debug2("UnCommentNLines(list,%s)\n",string);
  1548.  
  1549. sscanf(string,"%d", &N);
  1550.  
  1551. if (N < 1)
  1552.    {
  1553.    sprintf(OUTPUT,"Illegal number value in CommentNLines: %s\n",string);
  1554.    CfLog(cferror,OUTPUT,"");
  1555.    return false;
  1556.    }
  1557.  
  1558.  
  1559. if (CURRENTLINEPTR == NULL)  /* Shouldn't happen */
  1560.    {
  1561.    sprintf(OUTPUT,"File line-pointer undefined during editfile action\n");
  1562.    CfLog(cferror,OUTPUT,"");
  1563.    return true;
  1564.    }
  1565.  
  1566. ctr = 1;
  1567.  
  1568. for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR)
  1569.    {
  1570.    if (ip->name == NULL)
  1571.       {
  1572.       continue;
  1573.       }
  1574.  
  1575.    if (ctr > N)
  1576.       {
  1577.       break;
  1578.       }
  1579.    
  1580.    if (ctr == N)
  1581.       {
  1582.       EditVerbose("Terminating line: %s (Done)\n",ip->name);
  1583.       done = true;
  1584.       }
  1585.  
  1586.    if (strstr(ip->name,comm) == NULL)
  1587.       {
  1588.       CURRENTLINEPTR = ip->next;
  1589.       ctr++;
  1590.       continue;
  1591.       }
  1592.  
  1593.    EditVerbose("Uncomment line %s\n",ip->name);
  1594.    CURRENTLINEPTR = ip->next;
  1595.  
  1596.    if ((sp = malloc(strlen(ip->name)+2)) == NULL)
  1597.       {
  1598.       CfLog("No memory in UnCommentNLines\n","malloc");
  1599.       return false;
  1600.       }
  1601.  
  1602.    spc = sp;
  1603.    
  1604.    for (sp1 = ip->name; isspace(*sp1); sp1++)
  1605.       {
  1606.       *spc++ = *sp1;
  1607.       }
  1608.  
  1609.    *spc = '\0';
  1610.  
  1611.    sp2 = ip->name+strlen(ip->name);
  1612.  
  1613.    if ((strlen(end) != 0) && (strstr(ip->name,end) != NULL))
  1614.       {
  1615.       for (sp2 = ip->name+strlen(ip->name); strncmp(sp2,end,strlen(end)) != 0; sp2--)
  1616.      {
  1617.      }
  1618.  
  1619.       *sp2 = '\0';
  1620.       }
  1621.  
  1622.    strcat(sp,sp1+strlen(comm));
  1623.  
  1624.    if (sp2 != ip->name+strlen(ip->name))
  1625.       {
  1626.       strcat(sp,sp2+strlen(end));
  1627.       }
  1628.  
  1629.    ctr++;
  1630.  
  1631.    if (strcmp(sp,ip->name) != 0)
  1632.       {
  1633.       NUMBEROFEDITS++;
  1634.       }
  1635.    
  1636.    free(ip->name);
  1637.    ip->name = sp;
  1638.  
  1639.    if (done)
  1640.       {
  1641.       break;
  1642.       }
  1643.    }
  1644.  
  1645. if (ctr-1 < N)
  1646.    {
  1647.    sprintf(OUTPUT,"CommentNLines commented only %d lines (not %d)\n",ctr-1,N);
  1648.    CfLog(cfinform,OUTPUT,"");
  1649.    }
  1650.  
  1651. return true;
  1652. }
  1653.  
  1654. /********************************************************************/
  1655.  
  1656. ItemMatchesRegEx(item,regex)
  1657.  
  1658. char *item, *regex;
  1659.  
  1660. { regex_t rx,rxcache;
  1661.   regmatch_t pmatch; 
  1662.   size_t nmatch = 1;
  1663.  
  1664. Debug("ItemMatchesRegEx(%s %s)\n",item,regex);
  1665.  
  1666. if (regcomp(&rxcache,regex, REG_EXTENDED) != 0)
  1667.    {
  1668.    sprintf(OUTPUT,"Regular expression error for AbortAtLineMatching %s\n",regex);
  1669.    CfLog(cferror,OUTPUT,"regcomp");
  1670.    return true;
  1671.    }
  1672.  
  1673. bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ 
  1674. if (regexec(&rx,item,1,&pmatch,0) == 0)
  1675.    {
  1676.    if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(item)))
  1677.       {
  1678.       regfree(&rx);
  1679.       return true;
  1680.       }
  1681.    }
  1682.  
  1683. regfree(&rx);
  1684. return false;
  1685. }
  1686.  
  1687. /********************************************************************/
  1688.  
  1689. ReplaceWithFieldMatch(filestart,field,replace,split,filename)
  1690.  
  1691. struct Item **filestart;
  1692. char *field, *replace, *filename;
  1693. char split;
  1694.  
  1695. { struct Item *ip;
  1696.   char match[bufsize], linefield[bufsize], *sp, *sps, *spe;
  1697.   int matching_field = 0, fcount, i, linenum, count = 0;
  1698.  
  1699. Debug("ReplaceWithFieldMatch(%s,%s,%c)\n",field,replace,split);
  1700.  
  1701. if ((replace == NULL) || (strlen(replace) == 0))
  1702.    {
  1703.    EditVerbose("Ignoring empty line which doing ReplaceLinesMatchingField\n");
  1704.    return;
  1705.    }
  1706.   
  1707. matching_field = atoi(field);
  1708. bzero(match,bufsize);
  1709.  
  1710. fcount = 1;
  1711. sps = spe = NULL;
  1712.  
  1713. for (sp = replace; *sp != '\0'; sp++)
  1714.    {
  1715.    if (*sp == split)
  1716.       {
  1717.       if (fcount == matching_field)
  1718.      {
  1719.      spe = sp;
  1720.      break;
  1721.      }
  1722.       fcount++;
  1723.       }
  1724.  
  1725.    if ((fcount == matching_field) && (sps == NULL))
  1726.       {
  1727.       sps = sp;
  1728.       }
  1729.    }
  1730.  
  1731. if (fcount < matching_field)
  1732.    {
  1733.    CfLog(cfsilent,"File formats did not completely match in ReplaceLinesMatchingField\n","");
  1734.    sprintf(OUTPUT,"while editing %s\n",filename);
  1735.    CfLog(cfsilent,OUTPUT,"");
  1736.    return;
  1737.    }
  1738.  
  1739. if (spe == NULL)
  1740.    {
  1741.    spe = sp;
  1742.    }
  1743.  
  1744. for (i = 0, sp = sps; sp != spe; i++, sp++)
  1745.    {
  1746.    match[i] = *sp;
  1747.    }
  1748.   
  1749. Debug2("Edit: Replacing lines matching field %d == \"%s\"\n",matching_field,match);
  1750.  
  1751. linenum = 1;
  1752.  
  1753. for (ip = *filestart; ip != NULL; ip=ip->next, linenum++)
  1754.    {
  1755.    bzero(linefield,bufsize);
  1756.    fcount = 1;
  1757.    sps = spe = NULL;
  1758.  
  1759.    if (ip->name == NULL)
  1760.       {
  1761.       continue;
  1762.       }
  1763.  
  1764.    for (sp = ip->name; *sp != '\0'; sp++)
  1765.       {
  1766.          if (*sp == split)
  1767.          {
  1768.          if (fcount == matching_field)
  1769.            {
  1770.         spe = sp;
  1771.         break;
  1772.         }
  1773.          fcount++;
  1774.          }
  1775.  
  1776.       if ((fcount == matching_field) && (sps == NULL))
  1777.          {
  1778.          sps = sp;
  1779.          }
  1780.       }
  1781.  
  1782.    if (spe == NULL)
  1783.       {
  1784.       spe = sp;
  1785.       }
  1786.  
  1787.    if (sps == NULL)
  1788.       {
  1789.       sps = sp;
  1790.       }
  1791.  
  1792.    for (i = 0, sp = sps; sp != spe; i++, sp++)
  1793.       {
  1794.       linefield[i] = *sp;
  1795.       }
  1796.  
  1797.    if (strcmp(linefield,match) == 0)
  1798.       {
  1799.       EditVerbose("Replacing line %d (key %s)\n",linenum,match);
  1800.  
  1801.       count++;
  1802.  
  1803.       if (strcmp(replace,ip->name) == 0)
  1804.      {
  1805.      continue;
  1806.      }
  1807.  
  1808.       if (count > 1)
  1809.      {
  1810.      sprintf(OUTPUT,"Several lines in %s matched key %s\n",filename,match);
  1811.      CfLog(cfsilent,OUTPUT,"");
  1812.      }
  1813.  
  1814.       NUMBEROFEDITS++;
  1815.       
  1816.       free(ip->name);
  1817.  
  1818.       ip->name = (char *) malloc(strlen(replace)+1);
  1819.       strcpy(ip->name,replace);
  1820.       EditVerbose("Edit:   With (%s)\n",replace);
  1821.       }
  1822.    }
  1823. }
  1824.  
  1825. /********************************************************************/
  1826.  
  1827. AppendToLine(current,text,filename)
  1828.  
  1829. struct Item *current;
  1830. char *text, *filename;
  1831.  
  1832. { char *new;
  1833.  
  1834. if (strstr(current->name,text))
  1835.    {
  1836.    return;
  1837.    }
  1838.  
  1839. EditVerbose("Appending %s to line %-60s...\n",text,current->name);
  1840.  
  1841. new = malloc(strlen(current->name)+strlen(text)+1);
  1842. strcpy(new,current->name);
  1843. strcat(new,text);
  1844. NUMBEROFEDITS++;
  1845.  
  1846. free(current->name);
  1847. current->name = new;
  1848. }
  1849.  
  1850.  
  1851.  
  1852. /* EOF */
  1853.